package com.mrzhou.job.util;

import com.mrzhou.core.tool.utils.ClassUtil;
import com.mrzhou.job.entity.SchedulerJob;
import com.mrzhou.job.enums.SchedulerJobStatus;
import com.mrzhou.job.task.TestTask;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.scheduling.quartz.QuartzJobBean;

/**
 * @author qiang.zhou
 */
@Slf4j
public class SchedulerUtil {

    private static final String SCHEDULER_NAME = "Cloud_";

    /**
     * 获取定时器的key
     * @param jobId
     * @return
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(SCHEDULER_NAME + jobId);
    }

    /**
     * 获取定时器key
     * @param jobId
     * @return 定时器key
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(SCHEDULER_NAME + jobId);
    }

    /**
     * 获取表达式触发器
     * @param scheduler
     * @param jobId
     * @return
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("getCronTrigger 执行失败： {}", e);
        }
    }

    /**
     * 创建定时器
     * @param scheduler
     */
    public static void createJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            Class<? extends Job> clazz = ClassUtil.getSuperClass(schedulerJob.getJobClass(), QuartzJobBean.class);
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(getJobKey(schedulerJob.getJobId())).build();
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(schedulerJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(schedulerJob.getJobId()))
                    .withSchedule(scheduleBuilder).build();
            jobDetail.getJobDataMap().put(schedulerJob.JOB_PARAM_KEY, schedulerJob);
            scheduler.scheduleJob(jobDetail,cronTrigger);

            // 检查定时器是否是停止状态
            if (SchedulerJobStatus.PAUSE.equlas(schedulerJob.getStatus())) {
                updateJob(scheduler, schedulerJob);
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("createJob 执行失败：", e);
        }
    }

    /**
     * 更新定时器任务
     * @param scheduler
     * @param schedulerJob
     */
    public static void updateJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(schedulerJob.getJobId());
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(schedulerJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger cronTrigger = getCronTrigger(scheduler, schedulerJob.getJobId())
                    .getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder)
                    .build();
            cronTrigger.getJobDataMap().put(schedulerJob.JOB_PARAM_KEY, schedulerJob);
            scheduler.rescheduleJob(triggerKey, cronTrigger);
            // 检查定时器是否是停止状态
            if (SchedulerJobStatus.PAUSE.equlas(schedulerJob.getStatus())) {
                pauseJob(scheduler, schedulerJob);
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("updateJob 执行失败： ", e);
        }
    }

    /**
     * 暂停定时器任务
     * @param scheduler
     * @param schedulerJob
     */
    public static void pauseJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            scheduler.pauseJob(getJobKey(schedulerJob.getJobId()));
        } catch (SchedulerException e) {
            throw new RuntimeException("pauseJob 执行失败", e);
        }
    }

    /**
     * 恢复定时器任务
     * @param scheduler
     * @param schedulerJob
     */
    public static void resumeJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            scheduler.resumeJob(getJobKey(schedulerJob.getJobId()));
        } catch (SchedulerException e) {
            throw new RuntimeException("resumeJob 执行失败", e);
        }
    }

    /**
     * 删除定时器任务
     * @param scheduler
     * @param schedulerJob
     */
    public static void deletedJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            scheduler.deleteJob(getJobKey(schedulerJob.getJobId()));
        } catch (SchedulerException e) {
            throw new RuntimeException("deletedJob 执行失败", e);
        }
    }

    /**
     * 立即执行定时器任务
     * @param scheduler
     * @param schedulerJob
     */
    public static void runJob(Scheduler scheduler, SchedulerJob schedulerJob) {
        try {
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(schedulerJob.JOB_PARAM_KEY, schedulerJob);
            scheduler.triggerJob(getJobKey(schedulerJob.getJobId()), dataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException("runJob 执行失败", e);
        }
    }

    public static void main(String[] args) {
        System.out.println(ClassUtil.checkClassExtendsAndImpl(TestTask.class, Job.class));
    }

}
